// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rbchat.logic.more.avatar;

import java.io.File;
import java.util.HashMap;
import java.util.Observer;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

import com.eva.android.BitmapHelper;
import com.eva.android.IntentFactory;
import com.eva.android.widget.DataLoadingAsyncTask;
import com.x52im.rbchat.Const;
import com.x52im.rbchat.R;
import com.x52im.rbchat.network.http.HttpFileUploadHelper;
import com.x52im.rbchat.utils.ToolKits;

import net.x52im.mobileimsdk.android.ClientCoreSDK;

public class AvatarHelper
{
	private final static String TAG = AvatarHelper.class.getSimpleName();
	
	/**
	 * 查看指定用户的头像大图.
	 * 
	 * @param activity
	 * @param uid
	 */
	public static void showAvatarImage(Activity activity, String uid, Observer observerIfNoAvatar)
	{
		// 当有网络时，为确保即时看到最新头像，实时从网络拉取最新头像
		if(ClientCoreSDK.getInstance().isConnectedToServer()){
			activity.startActivity(IntentFactory.createImageViewActivityIntent_fromUrl(activity, AvatarHelper.getUserAvatarDownloadURL2022(uid), AvatarHelper.getUserAvatarSavedDir(activity)));
		}
		// 无网络时，为确保体验，打开的是缓存
		else{
			File cachedAvatarFile = AvatarHelper.getUserCachedAvatar(activity, uid);
			if(cachedAvatarFile != null)
				activity.startActivity(IntentFactory.createImageViewActivityIntent_fromFile(activity, cachedAvatarFile.getAbsolutePath()));
		}

//		File cachedAvatarFile = AvatarHelper.getUserCachedAvatar(activity, uid);
//		if(cachedAvatarFile != null)
//			activity.startActivity(IntentFactory.createImageViewActivityIntent_fromFile(activity, cachedAvatarFile.getAbsolutePath()));
//		else {
//			activity.startActivity(IntentFactory.createImageViewActivityIntent_fromUrl(activity, AvatarHelper.getUserAvatarDownloadURL2022(uid), AvatarHelper.getUserAvatarSavedDir(activity)));
//
////			if(observerIfNoAvatar != null)
////				observerIfNoAvatar.update(null, null);
////			else
////				WidgetUtils.showToast(activity, activity.getString(R.string.user_info_avatar_image_not_exists), ToastType.INFO);
//		}
	}
	
	/**
	 * 组织返回用户头像文件名.
	 * 
	 * @param uid
	 * @param md5ForCachedAvatar
	 * @return 形如“400069_43j4j3kjk3assdsdsdss.jpg”的头像保存文件名
	 */
	public static String getUserCachedAvatarFileName(String uid, String md5ForCachedAvatar)
	{
		if(uid == null || md5ForCachedAvatar == null)
		{
			Log.w(TAG, "无效的参数：uid == null || md5ForCachedAvatar == null!");
			return null;
		}
		return uid+"_"+md5ForCachedAvatar+".jpg";
	}
	
//	/**
//	 * 获得下载指定用户头像的URL（<b>服务端将根据用户本地缓存图片来
//	 * 智能判断是否要下载</b>（服务器的文件名称与本地一样当然就不需要下载了））.
//	 *
//	 * @param context
//	 * @param userUid 要下载头像的用户uid
//	 * @param userLocalCachedAvatar 缓存在本地的用户头像文件名称
//	 * @return
//	 */
//	public static String getUserAvatarDownloadURL(Context context, String userUid, String userLocalCachedAvatar)
//	{
//		return getUserAvatarDownloadURL(userUid, userLocalCachedAvatar, false);
//	}
//	/**
//	 * 获得<b>无条件（不管该用户有无本地头像缓存）</b>下载指定用户头像的URL.
//	 *
//	 * @param context
//	 * @param userUid 要下载头像的用户uid
//	 * @return
//	 */
//	public static String getUserAvatarDownloadURL(Context context, String userUid)
//	{
//		return getUserAvatarDownloadURL(userUid, null, true);
//	}
//
//	/**
//	 * 获得下载指定用户头像的完整http地址.
//	 * <p>
//	 * 形如：“http://192.168.88.138:8080/UserAvatarDownloadController?
//	 * action=ad&user_uid=400007&user_local_cached_avatar=400007_91c3e0d81b2039caa9c9899668b249e8.jpg
//	 * &enforceDawnload=0”。
//	 *
//	 * @param userUid 要下载头像的用户uid
//	 * @param userLocalCachedAvatar 用户缓存在本地的头像文件名（本参数只在enforceDawnload==false时有意义）
//	 * @param enforceDawnload true表示无论客户端有无提交缓存图片名称本方法都将无条件返回该用户头像（如果头像确实存在的话），否则
//	 * 将据客户端提交上来的可能的本地缓存文件来判断是否需要下载用户头像（用户头像没有被更新过当然就不需要下载了！）
//	 * @return 完整的http文件下载地址
//	 */
//	private static String getUserAvatarDownloadURL(String userUid, String userLocalCachedAvatar, boolean enforceDawnload)
//	{
//		String fileURL = MyApplication.AVATAR_DOWNLOAD_CONTROLLER_URL_ROOT
//				+"?action=ad"
//				+"&user_uid="+userUid
//				+(userLocalCachedAvatar==null?"":"&user_local_cached_avatar="+userLocalCachedAvatar)
//				+"&enforceDawnload="+(enforceDawnload?"1":"0");
//		return fileURL;
//	}

	/**
	 * 获得下载指定用户头像的完整http地址.
	 * <p>
	 * 该url保证强制让服务器每次都直接返回图片数据，而不需要由服务器自已根据user_local_cached_avatar这样的字段判断头像有没有变化。
	 * <p>
	 * <b>本方法当前主要用于Glide这样的图片缓存库，图片的缓存读取策略由Glide自身来决定，而不需要像之前的代码中那
	 * 样由业务代码自已精细化判断了！</b>
	 *
	 * @param userUid 用户的uid
	 * @return 头像图片加载url
	 * @since 8.0
	 */
	public static String getUserAvatarDownloadURL2022(String userUid)
	{
		String fileURL = Const.AVATAR_DOWNLOAD_CONTROLLER_URL_ROOT
				+"?action=ad"
				+"&user_uid="+userUid
				+"&enforceDawnload=1"
				// 尾巴上加一个签名字符串，可以放头像文件的md5码等，这样对于同一个uid的用户，在使用Glide这样的库时如
				// 果它的头像改变时能通过此签名的改变而取到最新的头像，否则Glide就没办法即时取到最新头像了
//				+(signature == null ?"":"&v="+signature)
				;
		return fileURL;
	}

	/**
	 * 返回存储用户头像的目录.（结尾带反斜线）.
	 * 
	 * @param context
	 * @return 如果SDCard等正常则返回目标路径，否则返回null
	 */
	public static String getUserAvatarSavedDirHasSlash(Context context)
	{
		String dir = getUserAvatarSavedDir(context);
		
		return dir ==  null? null : (dir + "/");
	}
	
	/**
	 * 返回存储用户头像的目录.
	 * 
	 * @param context
	 * @return 如果SDCard等正常则返回目标路径，否则返回null
	 */
	public static String getUserAvatarSavedDir(Context context)
	{
		String dir = null;
		File sysExternalStorageDirectory = ToolKits.getDefaultCacheDir();//Environment.getExternalStorageDirectory();
		if(sysExternalStorageDirectory != null && sysExternalStorageDirectory.exists())
		{
			dir = sysExternalStorageDirectory.getAbsolutePath() + Const.DIR_KCHAT_IMG_RELATIVE_DIR;
		}
		
		return dir;
	}
	
	/**
	 * 尝试删除指定uid用户缓存在本地的头像（图片文件）.
	 * 
	 * @param context
	 * @param uidToDelete 要删除的用户
	 * @param fileNameExceptToDelete 本参数可为null，不为空则表示：删除时要保留的文件名，此参数用于：刚下载完最新头像后又
	 * 要清理老头像时那么就应该跳过这个最新下载的，否则岂不是白白下载罗！
	 */
	public static void deleteUserAvatar(Context context, String uidToDelete, String fileNameExceptToDelete)
	{
		String avatarDirStr = AvatarHelper.getUserAvatarSavedDir(context);
		File avatarTempDir = new File(avatarDirStr);
		if(avatarTempDir != null && avatarTempDir.exists())
		{
			// 遍历缓存目录下的所有头像
			File[] allCachedAvatars = avatarTempDir.listFiles();
			if(allCachedAvatars != null && allCachedAvatars.length > 0)
			{
				for(File cachedAvatar : allCachedAvatars)
				{
					// 从文件名中取出缓存的用户uid（文件存在的格式形如：400002_0b272fca28252641231a94f63d8e25fa.jpg）
					String cachedAvatarFileName = cachedAvatar.getName();
					int separatorIndex = cachedAvatarFileName.indexOf("_");
					if(cachedAvatarFileName != null && (separatorIndex != -1))
					{
						String cachedUid = cachedAvatarFileName.substring(0, separatorIndex);
						// 如果该缓存正好是本用户的，就意味着这是老头像，删除它吧
						if(cachedUid != null && cachedUid.equals(uidToDelete))
						{
							// 如果要删除的这个文件刚好在受保护之列（应删除但排除在本次之外的文件），则本次保留之
							if(fileNameExceptToDelete != null && fileNameExceptToDelete.equals(cachedAvatarFileName))
								;
							else
								// 删除之
								cachedAvatar.delete();
						}
					}
				}
			}
		}
		else
		{
			Log.d(TAG, "【ChangeAvatar】用户的头像缓存目录不存，上传自已头像操作时无需尝试删除自已的头像缓存.");
		}
	}
	
	/**
	 * 返回指定用户缓存在本地的头像Bitmap对象.
	 * 
	 * @param context
	 * @param uid
	 * @param reqWidth、reqHeight 要转换成的像素数，比如：原图是640*640的大图，但用到的地方只需要200*200的图，
	 * 那么此值设为200*200为佳，因这将使得返回的Bitmap对象占用的内存为200*200而非640*640
	 * @return
	 * @see #getUserCachedAvatar(Context, String)
	 */
	public static Bitmap getUserCachedAvatarBitmap(Context context, String uid, int reqWidth, int reqHeight)
	{
		Bitmap bp = null;
		File cachedAvatar = getUserCachedAvatar(context, uid);
		if(cachedAvatar != null && cachedAvatar.exists())
		{
			bp = BitmapFactory.decodeFile(cachedAvatar.getAbsolutePath()
					// 裁剪图片的Bitmap（从而缩减内存占用）：裁剪内存占用不影响任何本地文件
					, BitmapHelper.computeSampleSize2(cachedAvatar.getAbsolutePath(), reqWidth, reqHeight));
		}
		return bp;
	}
	
	/**
	 * 返回指定用户缓存在本地地的头像File引用.
	 * <p>
	 * 注意：如果同一用户在该用户本地错误地存在多个头像（应该是在更新
	 * 缓存时没有删除成功的情况下发生的），则只返回修改时间为最新的文件（就这样吧，
	 * 更新缓存时会主动删除老的，也就等于程序有机会纠正这个错误）.
	 * 
	 * @param context
	 * @param uid
	 * @return 如果指定uid的用户存在本在头像缓存则返回File对象，否则返回null
	 */
	public static File getUserCachedAvatar(Context context, String uid)
	{
		String avatarDirStr = AvatarHelper.getUserAvatarSavedDir(context);
		File avatarTempDir = new File(avatarDirStr);
		
		File cachedAvatarForRet = null;
		if(uid != null && avatarTempDir != null && avatarTempDir.exists())
		{
			// 遍历缓存目录下的所有头像
			File[] allCachedAvatars = avatarTempDir.listFiles();
			if(allCachedAvatars != null && allCachedAvatars.length > 0)
			{
				for(File cachedAvatar : allCachedAvatars)
				{
					// 从文件名中取出缓存的用户uid（文件存在的格式形如：400002_0b272fca28252641231a94f63d8e25fa.jpg）
					String cachedAvatarFileName = cachedAvatar.getName();
					int separatorIndex = cachedAvatarFileName.indexOf("_");
					if(cachedAvatarFileName != null && (separatorIndex != -1))
					{
						String cachedUid = cachedAvatarFileName.substring(0, separatorIndex);
						// 如果该缓存正好是本用户的，那就直接返回
						if(cachedUid != null && cachedUid.equals(uid))
						{
							// 如果存在多张该用户的头像则取修改时间为最新的一张！
							if(cachedAvatarForRet == null
								|| cachedAvatar.lastModified() > cachedAvatarForRet.lastModified())
							{
								cachedAvatarForRet = cachedAvatar;
							}
						}
					}
				}
			}
		}
		
		return cachedAvatarForRet;
	}

	/**
	 * 用户头像上传异步线程.
	 * 
	 * @author Jack Jiang, 2013-12-13
	 * @version 1.0
	 */
	public static abstract class AvatarUploadAsync extends DataLoadingAsyncTask<Object, Integer, Boolean>
	{
		/** 
		 * 此Bitmap对象将用于上传成功后放到UI上显示（没有成功的话，需要手动recycle，以便即时回收内存！） .
		 * 为何要传入此对象而不干脆在UI要用到时从file中decode呢？因为在上传进行之前已经对原始文件进行了
		 * 压缩，而压缩时就要decode成bitmap对象，那么干脆就将压缩用完后的对象带过来从而提高效率、节省内存哦。 */
		private Bitmap bmOfTempAvatar = null;
		
		public AvatarUploadAsync(Activity parentActivity)
		{
			super(parentActivity, parentActivity.getString(R.string.user_info_avatar_uploading));
		}
		
		@Override
		protected Boolean doInBackground(Object... params)
		{
			Boolean result = Boolean.FALSE;
			if(params != null && params.length == 5)//6)//5)
			{
				String filePath = (String)params[0];
				String fileName = (String)params[1];
				String serverURL = (String)params[2];
				String localUserUid = (String)params[3];
				bmOfTempAvatar = (Bitmap)params[4];
				
//				// @since 2.1
//				// FIXME 20170306后此数据无需读取出来，日后将移除相关数据读取代码！！
//				byte[] fileData = (byte[])params[5];
				
				// 将本地用户的uid作为参数传递到服务端
				HashMap<String, String> requestProperties = new HashMap<String, String>();
				// 此参数名注意要与服务端保持一致哦
				requestProperties.put("user_uid", localUserUid);
				requestProperties.put("file_name", fileName);   // 因为服务端是支持多文件上传的API，所以此处单独把文件名带过去，方便使用！
				
				// 提交文件上传处理
				result = Boolean.valueOf(
						// ## 20170306前使用java对象上传文件的方法
//						AvatarDataUploadHttpHelper.uploadAvatarFile(fileName, localUserUid, fileData)
						// ## 20170306后使用okhttp3上传文件的方法
						HttpFileUploadHelper.uploadFile(filePath, fileName, serverURL, requestProperties)
//						HttpUploadHelper2.uploadFile(filePath, fileName, serverURL, requestProperties)
//						HttpUploadHelper.post(filePath, serverURL, requestProperties)
						);
			}
			else
				Log.e(AvatarUploadAsync.class.getSimpleName(), "无效的参数个数："+(params == null?0:params.length));
			
			return result;
		}
		
		@Override
		protected void onPostExecuteImpl(Object _result) 
		{
			if(_result != null)
			{
				Boolean result = (Boolean)_result;
				if(result)
					afterSucess(bmOfTempAvatar);
				else
				{
					// 如果上传失败则无需显示bitmap到ui上，此外要手动释放哦，以便节省内存！
					if(bmOfTempAvatar != null && !bmOfTempAvatar.isRecycled())
						bmOfTempAvatar.recycle();
					afterFaild();
				}
			}
	    }
		
		/**
		 * 上传头像成功后要调用的方法.
		 */
		protected abstract void afterSucess(Bitmap bmOfTempAvatar);
		
		/**
		 * 上传头像失败后要调用的方法.
		 */
		protected abstract void afterFaild();
	}
}
